package com.ruoyi.technician.controller;

import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.check.CheckEmptyUtil;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.redis.RedisUtil;
import com.ruoyi.merchant.mapper.MerchantMapper;
import com.ruoyi.order.domain.TechnicianItemOrder;
import com.ruoyi.order.mapper.TechnicianItemOrderMapper;
import com.ruoyi.technician.domain.Technician;
import com.ruoyi.technician.mapper.GradeConfigMapper;
import com.ruoyi.technician.mapper.TechnicianConsumeDetailMapper;
import com.ruoyi.technician.mapper.TechnicianMapper;
import com.ruoyi.technician.service.ITechnicianService;
import com.ruoyi.technician.vo.*;
import com.ruoyi.technicianAudit.mapper.RecruitmentMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 技师管理Controller
 *
 * @author ruoyi
 * @date 2025-04-07
 */
@RestController
@RequestMapping("/technician/technician")
public class TechnicianController extends BaseController {
    @Autowired
    private ITechnicianService technicianService;
    @Resource
    private GradeConfigMapper gradeConfigMapper;
    @Resource
    private MerchantMapper merchantMapper;
    @Resource
    private TechnicianMapper technicianMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private TechnicianItemOrderMapper technicianItemOrderMapper;
    @Resource
    private TechnicianConsumeDetailMapper technicianConsumeDetailMapper;
    @Resource
    private RecruitmentMapper recruitmentMapper;


    /**
     * 查询技师管理列表
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:list')")
    @GetMapping("/list")
    public TableDataInfo list(Technician technician) {
        startPage();
        List<Technician> list = technicianService.selectTechnicianList(technician);
        if (!CheckEmptyUtil.isEmpty(list)) {
            for (Technician technician1 : list) {
                String name = gradeConfigMapper.getName(technician1.getGradeId());
                technician1.setGradeName(!CheckEmptyUtil.isEmpty(name) ? name : "");
                String name1 = merchantMapper.getName(technician1.getMerchantId());
                technician1.setMerchantName(!CheckEmptyUtil.isEmpty(name1) ? name1 : "");
                String userName = technicianMapper.selectUserName(technician1.getUserId());
                technician1.setUserName(!CheckEmptyUtil.isEmpty(userName) ? userName : "");
                String typeName = technicianMapper.selectTypeName(technician1.getTechnicianType());
                technician1.setTechnicianTypeName(!CheckEmptyUtil.isEmpty(typeName) ? typeName : "");
                if (!CheckEmptyUtil.isEmpty(technician1.getTechnicianInvitedCode())) {
                    String brokerName = technicianMapper.selectPartnerBrokerName(technician1.getTechnicianInvitedCode());
                    technician1.setPartnerBrokerName(!CheckEmptyUtil.isEmpty(brokerName) ? brokerName : "");
                }
            }
        }
        return getDataTable(list);
    }

    /**
     * 导出技师管理列表
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:export')")
    @Log(title = "技师管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Technician technician) {
        List<Technician> list = technicianService.selectTechnicianList(technician);
        if (!CheckEmptyUtil.isEmpty(list)) {
            for (Technician technician1 : list) {
                String name = gradeConfigMapper.getName(technician1.getGradeId());
                technician1.setGradeName(!CheckEmptyUtil.isEmpty(name) ? name : "");
                String name1 = merchantMapper.getName(technician1.getMerchantId());
                technician1.setMerchantName(!CheckEmptyUtil.isEmpty(name1) ? name1 : "");
                String userName = technicianMapper.selectUserName(technician1.getUserId());
                technician1.setUserName(!CheckEmptyUtil.isEmpty(userName) ? userName : "");
                String typeName = technicianMapper.selectTypeName(technician1.getTechnicianType());
                technician1.setTechnicianTypeName(!CheckEmptyUtil.isEmpty(typeName) ? typeName : "");
                if (!CheckEmptyUtil.isEmpty(technician1.getTechnicianInvitedCode())) {
                    String brokerName = technicianMapper.selectPartnerBrokerName(technician1.getTechnicianInvitedCode());
                    technician1.setPartnerBrokerName(!CheckEmptyUtil.isEmpty(brokerName) ? brokerName : "");
                }
            }
        }
        ExcelUtil<Technician> util = new ExcelUtil<Technician>(Technician.class);
        util.exportExcel(response, list, "技师管理数据");
    }

    /**
     * 获取技师管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        Technician technician = technicianService.selectTechnicianById(id);
        if (!CheckEmptyUtil.isEmpty(technician)) {
            String name = gradeConfigMapper.getName(technician.getGradeId());
            technician.setGradeName(!CheckEmptyUtil.isEmpty(name) ? name : "");
            String name1 = merchantMapper.getName(technician.getMerchantId());
            technician.setMerchantName(!CheckEmptyUtil.isEmpty(name1) ? name1 : "");
            String userName = technicianMapper.selectUserName(technician.getUserId());
            technician.setUserName(!CheckEmptyUtil.isEmpty(userName) ? userName : "");
            String typeName = technicianMapper.selectTypeName(technician.getTechnicianType());
            technician.setTechnicianTypeName(!CheckEmptyUtil.isEmpty(typeName) ? typeName : "");
            if (!CheckEmptyUtil.isEmpty(technician.getTechnicianInvitedCode())) {
                String brokerName = technicianMapper.selectPartnerBrokerName(technician.getTechnicianInvitedCode());
                technician.setPartnerBrokerName(!CheckEmptyUtil.isEmpty(brokerName) ? brokerName : "");
            }

            //在线时长
            TechnicianOnlineTimeRedis technicianOnlineTimeRedisVo = JSONObject.parseObject(redisUtil.hget("TECHNICIAN_ONLINE_TIME", technician.getId().toString()), TechnicianOnlineTimeRedis.class);
            if (CheckEmptyUtil.isEmpty(technicianOnlineTimeRedisVo)) {
                technician.setTotalOnlineTime("0");
            } else {
                technician.setTotalOnlineTime(DateUtil.formatBetween(technicianOnlineTimeRedisVo.getTotalOnlineTime(), BetweenFormatter.Level.HOUR));
            }

            //加钟率
            Map<String, Object> map = calculateBellRate(technician.getId());
            BigDecimal bellRate = (BigDecimal) map.get("bellRate");
            technician.setAddBellRate(bellRate);
            //服务总时长
            Integer serviceTime = (Integer) map.get("serviceTime");
            technician.setTotalServiceTime(serviceTime);

            technician.setBalance(BigDecimal.ZERO);

            // 收入金额
            BigDecimal addAmount = technicianConsumeDetailMapper.selectAddAmount(technician.getId(), 1);
            //已提现金额
            BigDecimal payoutAmount = technicianConsumeDetailMapper.selectPayoutAmount(technician.getId());
            //可提现金额
            technician.setBalance(addAmount.subtract(payoutAmount));

        }
        return success(technician);
    }


    /**
     * 计算加钟率 和 服务总时长
     *
     * @param technicianId
     * @return
     * @Date 2025 4月 11 11:08
     */
    private Map<String, Object> calculateBellRate(Long technicianId) {
        Map<String, Object> map = new HashMap<>();
        // 加钟订单数
        List<TechnicianItemOrder> bellOrder = technicianItemOrderMapper.seleBellOrder(technicianId);
        //总订单数
        Integer normalOrderCount = 0;
        //服务时长
        Integer serviceTime = 0;
        List<TechnicianItemOrder> technicianItemOrders = technicianItemOrderMapper.selectList(technicianId);
        if (!CheckEmptyUtil.isEmpty(technicianItemOrders)) {
            for (TechnicianItemOrder technicianItemOrder : technicianItemOrders) {
                List<TechnicianItemOrder> upgradeOrder = technicianItemOrderMapper.selectUpgradeCount(technicianId, technicianItemOrder.getOrderNo());
                normalOrderCount += (CheckEmptyUtil.isEmpty(upgradeOrder)) ? 1 : upgradeOrder.size();

                serviceTime += ((CheckEmptyUtil.isEmpty(upgradeOrder) ? technicianItemOrder.getItemTime() : upgradeOrder.stream().mapToInt(TechnicianItemOrder::getItemTime).sum()));
            }
        }
        if (!CheckEmptyUtil.isEmpty(bellOrder)) {
            serviceTime += (bellOrder.stream().mapToInt(TechnicianItemOrder::getItemTime).sum());
        }

        map.put("serviceTime", serviceTime);
        BigDecimal bellRate = (CheckEmptyUtil.isEmpty(bellOrder) || normalOrderCount == 0) ? BigDecimal.ZERO
                : new BigDecimal(bellOrder.size()).divide(new BigDecimal(normalOrderCount), 2, RoundingMode.HALF_UP);
        map.put("bellRate", bellRate);
        return map;
    }


    /**
     * 获取技师关联的服务
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:selectItem')")
    @PostMapping(value = "/selectItem")
    public AjaxResult selectItem(@RequestBody SelectItemVo requestVo) {
        Technician technician = technicianService.selectTechnicianById(requestVo.getTid());


        if (!CheckEmptyUtil.isEmpty(technician.getServiceItem())) {
            String itemIds = technicianMapper.selectItemIdByTid(requestVo.getTid());
            if (!CheckEmptyUtil.isEmpty(itemIds)) {
                List<Long> longs = Arrays.stream(itemIds.split(",")) // 拆分字符串
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
                List<ServiceItems> serviceItems = technicianMapper.selectItem(longs);
                return success(new PageInfo<>(serviceItems));
            }
        }
        return success(new PageInfo<>());
    }

    /**
     * 取消技师关联的服务
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:selectItem')")
    @PostMapping(value = "/updateItem")
    public AjaxResult updateItem(@RequestBody UpdateItemVo requestVo) {
        Technician technician = technicianService.selectTechnicianById(requestVo.getTid());
        String serviceItem = technician.getServiceItem();
        Long itemId = requestVo.getItemId();
        serviceItem = removeItemFromServiceItem(serviceItem, itemId);
        Integer updateItem = technicianMapper.updateItem(requestVo.getTid(), serviceItem);
        return success(updateItem);
    }

    // 在TechnicianController.java中添加以下方法
    public String removeItemFromServiceItem(String serviceItem, Long itemId) {
        String itemIdStr = String.valueOf(itemId);

        // 如果字符串中只有一个数字，且等于要删除的数字
        if (serviceItem.equals(itemIdStr)) {
            return "";
        }

        // 如果要删除的数字后面有逗号（包括位于开头和中间的情况）
        if (serviceItem.startsWith(itemIdStr + ",")) {
            // 如果要删除的数字位于开头
            if (serviceItem.length() == itemIdStr.length() + 1) {
                // 只有一个数字和逗号，删除后变为空字符串
                return "";
            } else {
                // 删除数字及其后面的逗号
                return serviceItem.substring(itemIdStr.length() + 1);
            }
        } else if (serviceItem.contains("," + itemIdStr + ",")) {
            // 如果要删除的数字位于中间
            int startIndex = serviceItem.indexOf("," + itemIdStr + ",");
            return serviceItem.substring(0, startIndex) + "," + serviceItem.substring(startIndex + itemIdStr.length() + 2);
        } else if (serviceItem.endsWith("," + itemIdStr)) {
            // 如果要删除的数字位于末尾，且前面有逗号
            return serviceItem.substring(0, serviceItem.length() - itemIdStr.length() - 1);
        } else if (serviceItem.endsWith(itemIdStr) && !serviceItem.endsWith("," + itemIdStr)) {
            // 如果要删除的数字位于末尾，且后面没有逗号
            return serviceItem.substring(0, serviceItem.length() - itemIdStr.length());
        }

        // 如果要删除的数字不存在于字符串中，返回原字符串
        return serviceItem;
    }

    /**
     * 关联技师关联的服务
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:selectItem')")
    @PostMapping(value = "/addItem")
    public AjaxResult addItem(@RequestBody UpdateItemVo requestVo) {
        // 使用Stream API将列表转换为逗号拼接的字符串
        String itemIds = requestVo.getItemIds().stream()
                .map(String::valueOf) // 将Long转换为String
                .collect(Collectors.joining(",")); // 使用逗号连接字符串
        Integer updateItem = technicianMapper.addItem(requestVo.getTid(), itemIds);
        return success(updateItem);
    }


    /**
     * 获取技师服务订单
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:selectItem')")
    @PostMapping(value = "/selectTechnicianOrder")
    public AjaxResult selectTechnicianOrder(@RequestBody SelectItemVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<SelectTechnicianOrderResponseVo> responseVoList = technicianMapper.selectTechnicianOrder(requestVo.getTid());
        List<SelectTechnicianOrderResponseVo> voList = new ArrayList<>();
        if (!CheckEmptyUtil.isEmpty(responseVoList)) {
            PageInfo<SelectTechnicianOrderResponseVo> source = new PageInfo<>(responseVoList);
            PageInfo<SelectTechnicianOrderResponseVo> target = new PageInfo<>();
            BeanUtils.copyProperties(source, target);
            for (SelectTechnicianOrderResponseVo orderResponseVo : source.getList()) {
                SelectTechnicianOrderResponseVo vo = new SelectTechnicianOrderResponseVo();
                BeanUtils.copyProperties(orderResponseVo, vo);
                BigDecimal income = technicianMapper.selectIncome(orderResponseVo.getOrderNo());
                vo.setRealIncome(income);
                voList.add(vo);
            }

            target.setList(voList);
            return success(target);
        }
        return success(new PageInfo<>());
    }

    /**
     * 新增技师管理
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:add')")
    @Log(title = "技师管理", businessType = BusinessType.INSERT)
    @PostMapping
    @RepeatSubmit(interval = 500, message = "正在添加,请稍后")
    public AjaxResult add(@RequestBody Technician technician) {
        return toAjax(technicianService.insertTechnician(technician));
    }

    /**
     * 修改技师管理
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
    @Log(title = "技师管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Technician technician) {
        return toAjax(technicianService.updateTechnician(technician));
    }

    /**
     * 删除技师管理
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:remove')")
    @Log(title = "技师管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(technicianService.deleteTechnicianByIds(ids));
    }

    /**
     * 新增技师中未关联的项目
     *
     * @param requestVo
     * @return
     * @Date 2025 4月 18 10:59
     */
    @PostMapping("selectAddNotRelevancyItemList")
    public TableDataInfo selectAddNotRelevancyItemList(@RequestBody SelectAddNotRelevancyItemListVo requestVo) {
        // 获取所有item的ID
        List<Long> list2 = technicianMapper.selectAllItemId();

        List<Long> result = new ArrayList<>();

        if (!CheckEmptyUtil.isEmpty(requestVo.getItemIds())) {
            Set<Long> itemIdSet = new HashSet<>(requestVo.getItemIds());
            // 使用Stream过滤list2，去除list1中的元素
            result = list2.stream()
                    .filter(tid -> !itemIdSet.contains(tid))
                    .collect(Collectors.toList());
        } else {
            result = list2;
        }
        if (result.isEmpty()) {
            result.add(0L);
        }
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<ServiceItems> itemsList = technicianMapper.selectItemList(requestVo.getKeyWord(), result);

        return getDataTable(itemsList);
    }


    /**
     * 新增技师中已关联的项目
     */
    @PreAuthorize("@ss.hasPermi('technician:technician:selectItem')")
    @PostMapping(value = "/selectAddIsRelevancyItemList")
    public TableDataInfo selectAddIsRelevancyItemList(@RequestBody SelectAddNotRelevancyItemListVo requestVo) {
        List<Long> result = new ArrayList<>();
        if (!CheckEmptyUtil.isEmpty(requestVo.getItemIds())) {
            result = requestVo.getItemIds();
        }
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<ServiceItems> itemsList = technicianMapper.selectItemList(requestVo.getKeyWord(), result);

        return getDataTable(itemsList);
    }

    /**
     * 查询未关联技师的用户
     *
     * @param requestVo
     * @return
     * @Date 2025 5月 27 09:05
     */
    @PostMapping(value = "/selectUserNotRelevancyTechnicianList")
    public TableDataInfo selectUserNotRelevancyTechnicianList(@RequestBody SelectAddNotRelevancyItemListVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<SelectUserNotRelevancyTechnicianListVo> userList = technicianMapper.selectUserNotRelevancyTechnicianList(requestVo);
        List<SelectUserNotRelevancyTechnicianListVo> responseVoList = new ArrayList<>();
        if (!CheckEmptyUtil.isEmpty(userList)) {
            //查询技师申请中是否有待审核的关联用户
            List<Long> userIds = recruitmentMapper.selectUserId();
            if (!CheckEmptyUtil.isEmpty(userIds)) {
                for (SelectUserNotRelevancyTechnicianListVo selectUserNotRelevancyTechnicianListVo : userList) {
                    SelectUserNotRelevancyTechnicianListVo vo = new SelectUserNotRelevancyTechnicianListVo();
                    if (!userIds.contains(selectUserNotRelevancyTechnicianListVo.getUserId())) {
                        vo.setUserId(selectUserNotRelevancyTechnicianListVo.getUserId());
                        vo.setUserAvatar(selectUserNotRelevancyTechnicianListVo.getUserAvatar());
                        vo.setUserName(selectUserNotRelevancyTechnicianListVo.getUserName());
                        vo.setUserTel(selectUserNotRelevancyTechnicianListVo.getUserTel());
                        responseVoList.add(vo);
                    }
                }
            } else {
                responseVoList = userList;
            }
        }

        return getDataTable(responseVoList);
    }
}
